﻿#include "FITKAbaqusAdaptorAmplitude.h"
#include "InpKeyLineSpliter.h"
#include "FITKAbaqusINPReader.h"
#include "FITKAbaqusINPWriter.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAbstractAmplitude.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAmplitudePeriodic.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAmplitudeTabular.h"
#include "FITK_Kernel/FITKAppFramework/FITKMessage.h"
#include <QTextStream>
#include <QList>
#include <QDebug>

namespace IO
{
    QString FITKAbaqusAdaptorAmplitude::getAdaptorClass()
    {
        //类名
        return "FITKAbaqusAdaptorAmplitude";
    }

    bool FITKAbaqusAdaptorAmplitude::adaptR()
    {
        Interface::FITKAbaAbstractAmplitude* amplitude = dynamic_cast<Interface::FITKAbaAbstractAmplitude*>(_dataObj);
        if (!amplitude || !_reader)return false;
        //回退一行，处理关键字信息
        _reader->backLine();

        bool readOK = false;
        QString line = _reader->readLine();
        //处理关键字数据
        InpKeyLineSpliter spl(line, _reader);
        if (!spl.hasKey("name"))
            return false;
        //获取名称
        QString name = spl["name"];
        amplitude->setDataObjectName(name);
        //获取类型
        Interface::FITKAbaAbstractAmplitude::FITKAbaAmplitudeType type = amplitude->getAmplitudeType();
        if (type == Interface::FITKAbaAbstractAmplitude::FITKAbaAmplitudeType::Periodic)
        {
            readOK = this->amplitudePeriodicR();
        }
        else if (type == Interface::FITKAbaAbstractAmplitude::FITKAbaAmplitudeType::Tabular)
        {
            readOK = this->amplitudeTabularR();
        }
        return readOK;
    }

    bool FITKAbaqusAdaptorAmplitude::adaptW()
    {
        //获取数据
        Interface::FITKAbaAbstractAmplitude* amplitude = dynamic_cast<Interface::FITKAbaAbstractAmplitude*>(_dataObj);
        if (!amplitude || !_writer) return false;
        bool writeOK = false;
        //获取类型，写出不同类型的格式
        Interface::FITKAbaAbstractAmplitude::FITKAbaAmplitudeType type = amplitude->getAmplitudeType();
        if (type == Interface::FITKAbaAbstractAmplitude::FITKAbaAmplitudeType::Periodic)
        {
            writeOK = this->amplitudePeriodicW();
        }
        else if (type == Interface::FITKAbaAbstractAmplitude::FITKAbaAmplitudeType::Tabular)
        {
            writeOK = this->amplitudeTabularW();
        }
        return writeOK;
    }

    bool FITKAbaqusAdaptorAmplitude::amplitudeTabularR()
    {
        //表格类型读取
        Interface::FITKAbaAmplitudeTabular* amplitude = dynamic_cast<Interface::FITKAbaAmplitudeTabular*>(_dataObj);
        if (!amplitude || !_reader)return false;

        //回退一行，处理关键字信息
        _reader->backLine();
        QString line = _reader->readLine();
        bool ok = false;
        //处理关键字数据
        InpKeyLineSpliter spl(line, _reader);
        //设置时间跨度
        amplitude->setTimeSpan(Interface::FITKAbaAbstractAmplitude::TimeSpan::StepTime);
        if (spl["time"].toUpper() == "TOTAL TIME")
            amplitude->setTimeSpan(Interface::FITKAbaAbstractAmplitude::TimeSpan::TotalTime);
        //设置平滑类型
        amplitude->setSmoothingType(Interface::FITKAbaAbstractAmplitude::SmoothingType::UseSolverDefault);
        if (spl.hasKey("smooth"))
        {
            double v = spl["smooth"].toDouble(&ok);
            if (!ok)return false;
            amplitude->setSmoothingType(Interface::FITKAbaAbstractAmplitude::SmoothingType::Specify);
            amplitude->setSmoothingValue(v);
        }
        //读取数据
        int num = 0;
        while (!_reader->atEnd())
        {
            line = _reader->readLine();
            if (line.startsWith('*'))
                break;
            QString str = line.trimmed();
            if (str.end() == QChar(','))
                str.chop(1);
            QStringList strList = str.split(',');
            //获取时间和幅值
            for (QString value : strList)
            {
                double v = value.trimmed().toDouble(&ok);
                if (!ok)return false;
                int index = num / 2;
                if (amplitude->getNumberOfRows() == index)
                    amplitude->insertRow(index);
                if (num % 2)
                    amplitude->setAmplitude(v, index);
                else
                    amplitude->setTime(v, index);
                ++num;
            }
        }
        if (num == 0)return false;
        return true;
    }

    bool FITKAbaqusAdaptorAmplitude::amplitudePeriodicR()
    {
        //周期类型读取
        Interface::FITKAbaAmplitudePeriodic* amplitude = dynamic_cast<Interface::FITKAbaAmplitudePeriodic*>(_dataObj);
        if (!amplitude || !_reader)return false;
        //回退一行，处理关键字信息
        _reader->backLine();
        QString line = _reader->readLine();
        //处理关键字数据
        InpKeyLineSpliter spl(line, _reader);
        //设置时间跨度
        amplitude->setTimeSpan(Interface::FITKAbaAbstractAmplitude::TimeSpan::StepTime);
        if (spl["time"].toUpper() == "TOTAL TIME")
            amplitude->setTimeSpan(Interface::FITKAbaAbstractAmplitude::TimeSpan::TotalTime);
        //读取数据
        line = _reader->readLine();
        QStringList slis = line.split(',');
        if (slis.size() < 4)return false;
        //获取项数、循环频率、开始时间、初始幅值
        bool ok = false;
        int flag = slis.at(0).trimmed().toInt(&ok);
        if (!ok)return false;
        double v = slis.at(1).trimmed().toDouble(&ok);
        if (!ok)return false;
        amplitude->setCircularFrequency(v);
        v = slis.at(2).trimmed().toDouble(&ok);
        if (!ok)return false;
        amplitude->setStartingTime(v);
        v = slis.at(3).trimmed().toDouble(&ok);
        if (!ok)return false;
        amplitude->setInitialAmplitude(v);
        
        int num = 0;
        while (!_reader->atEnd())
        {
            line = _reader->readLine();
            if (line.startsWith('*'))
                break;
            QString str = line.trimmed();
            if (str.end() == QChar(','))
                str.chop(1);
            QStringList strList = str.split(',');
            //获取时间和幅值
            for (QString value : strList)
            {
                v = value.trimmed().toDouble(&ok);
                if (!ok)return false;
                int index = num / 2;
                if (amplitude->getNumberOfRows() == index)
                    amplitude->insertRow(index);
                if (num % 2)
                    amplitude->setB(v, index);
                else
                    amplitude->setA(v, index);
                ++num;
            }
        }
        //校验项数是否一致
        if (num / 2 != flag)return false;
        return true;
    }

    bool FITKAbaqusAdaptorAmplitude::amplitudeTabularW()
    {
        //写出表格类型
        Interface::FITKAbaAmplitudeTabular* amplitude = dynamic_cast<Interface::FITKAbaAmplitudeTabular*>(_dataObj);
        if (!amplitude || !_writer)return false;
        //写出*Amplitude
        QTextStream* stream = _writer->getStream();
        QString ampName = amplitude->getDataObjectName();
        ampName = ampName.contains(' ') ? QString("\"%1\"").arg(ampName) : ampName;
        QString writeLine = QString("*Amplitude, name=%1").arg(ampName);
        if (amplitude->getTimeSpan() == Interface::FITKAbaAbstractAmplitude::TimeSpan::TotalTime)
            writeLine += ", time=TOTAL TIME";
        if (amplitude->getSmoothingType() == Interface::FITKAbaAbstractAmplitude::SmoothingType::Specify)
            writeLine += QString(", smooth=%1").arg(_writer->double2String(amplitude->getSmoothingValue(), 8, 0));
        *stream << writeLine << endl;
        //写出Amplitude的时间和幅值
        int count = amplitude->getNumberOfRows();
        QStringList str;
        for (int i = 0; i < count; ++i)
        {
            if (i != 0 && str.size() % 8 == 0)
            {
                *stream << str.join(", ") << endl;
                str.clear();
            }
            double value = amplitude->getTime(i);
            str.append(_writer->double2String(value, 15, 15));
            value = amplitude->getAmplitude(i);
            str.append(_writer->double2String(value, 15, 15));
        }
        //是否还有数据没有写出
        if (!str.isEmpty())
            *stream << str.join(", ") << endl;
        return true;
    }

    bool FITKAbaqusAdaptorAmplitude::amplitudePeriodicW()
    {
        //写出周期类型
        Interface::FITKAbaAmplitudePeriodic* amplitude = dynamic_cast<Interface::FITKAbaAmplitudePeriodic*>(_dataObj);
        if (!amplitude || !_writer)return false;
        //写出*Amplitude
        QTextStream* stream = _writer->getStream();
        QString ampName = amplitude->getDataObjectName();
        ampName = ampName.contains(' ') ? QString("\"%1\"").arg(ampName) : ampName;
        QString writeLine = QString("*Amplitude, name=%1").arg(ampName);
        if (amplitude->getTimeSpan() == Interface::FITKAbaAbstractAmplitude::TimeSpan::TotalTime)
            writeLine += ", time=TOTAL TIME";
        writeLine += ", definition=PERIODIC";
        *stream << writeLine << endl;
        //写出项数、循环频率、开始时间、初始幅值
        int count = amplitude->getNumberOfRows();
        QString circularFrequency = _writer->double2String(amplitude->getCircularFrequency(), 9, 16);
        QString startingTime = _writer->double2String(amplitude->getStartingTime(), 9, 16);
        QString initialAmplitude = _writer->double2String(amplitude->getInitialAmplitude(), 9, 16);
        writeLine = QString("%1,%2,%3,%4").arg(count).arg(circularFrequency).arg(startingTime).arg(initialAmplitude);
        *stream << writeLine << endl;
        //写出Amplitude的A\B
        QStringList str;
        for (int i = 0; i < count; ++i)
        {
            if (i != 0 && str.size() % 8 == 0)
            {
                *stream << str.join(',') << endl;
                str.clear();
            }
            double value = amplitude->getA(i);
            str.append(_writer->double2String(value, 9, 16));
            value = amplitude->getB(i);
            str.append(_writer->double2String(value, 9, 16));
        }
        //是否还有数据没有写出
        if(!str.isEmpty())
            *stream << str.join(',') << endl;
        return true;
    }

}